package com.gylang.passport.service.login.impl;

import cn.hutool.core.map.MapUtil;
import com.gylang.common.constant.CommonConstant;
import com.gylang.common.dto.CommonResult;
import com.gylang.common.enums.BaseResultCode;
import com.gylang.common.exception.BaseException;
import com.gylang.core.util.OrderUtils;
import com.gylang.passport.domain.dto.LoginDTO;
import com.gylang.passport.service.login.LoginBeforeProcess;
import com.gylang.passport.service.login.LoginBeforeProcessHandler;
import com.gylang.passport.service.login.LoginService;
import com.gylang.passport.service.login.LoginServiceManager;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author gylang
 * data 2021/1/8
 */
@Service
public class LoginServiceManagerImpl implements LoginServiceManager, InitializingBean {


    @Autowired(required = false)
    private List<LoginBeforeProcessHandler> processHandlerList;
    @Autowired(required = false)
    private Map<String, LoginService<?>> loginService;

    /**
     * 调用登录接口
     *
     * @param dto 登录参数
     * @return 登录结果
     */
    @Override
    public CommonResult<Object> doLogin(LoginDTO dto) {

        String bizKey = transferToBizKey(dto);
        LoginService<Object> login = (LoginService<Object>) this.loginService.get(bizKey);
        if (null != login) {
            return login.login(dto);
        }
        throw new BaseException(BaseResultCode.LOGIN_ERROR.getCode(), "当前登录业务不存在");
    }

    /**
     * 默认登录方法
     *
     * @param dto 登录参数
     * @return 登录结果
     */
    @Override
    public CommonResult<Object> simpleLogin(LoginDTO dto) {

        return doLogin(dto);
    }

    /**
     * 默认登录方法
     *
     * @param dto 登录参数
     * @return 登录结果
     */
    @Override
    public CommonResult<Object> login(LoginDTO dto) {

        // 登录前处理器
        if (null != processHandlerList) {
            for (LoginBeforeProcessHandler handler : processHandlerList) {
                if (handler.support(dto)) {
                    handler.process(dto);
                }
            }
        }
        return doLogin(dto);
    }

    @Override
    public CommonResult<Object> login(LoginDTO dto, LoginBeforeProcess process) {

        // 登录前校验 同意处理判断是否需要进行校验码操作
        process.process(dto);

        return doLogin(dto);
    }

    @Override
    public CommonResult<Object> login(LoginDTO dto, LoginBeforeProcess... process) {

        // 登录前校验 同意处理判断是否需要进行校验码操作
        Arrays.sort(process, new OrderUtils.ObjectOrder());
        return doLogin(dto);
    }


    @Override
    public String transferToBizKey(LoginDTO dto) {
        if (null == dto) {
            throw new BaseException(BaseResultCode.LOGIN_ERROR.getCode(), "当前登录业务不存在");
        }
        return dto.getType() + CommonConstant.SPLIT_STR + dto.getChannel();
    }

    @Override
    public void afterPropertiesSet() {

        if (null == loginService) {
            loginService = MapUtil.empty();
        }
        loginService = loginService.values().stream()
                .collect(Collectors.toMap(LoginService::bizKey, lg -> lg));
    }
}
